package com.mentalhealthplatform.utils.decryptUtils.property;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.util.HashMap;
import java.util.Map;

public class DecryptEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private static final String ENCRYPTED_PREFIX = "ENC_";  // 加密值的前缀

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        // 创建一个新的 Map 来存储解密后的配置
        Map<String, Object> decryptedProperties = new HashMap<>();

        // 遍历所有的 PropertySource
        for (PropertySource<?> propertySource : environment.getPropertySources()) {
            if (propertySource instanceof MapPropertySource) {
                MapPropertySource mapPropertySource = (MapPropertySource) propertySource;

                // 遍历配置源中的所有属性
                for (Map.Entry<String, Object> entry : mapPropertySource.getSource().entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();

                    // 检查值是否为 OriginTrackedValue，并提取实际值
                    if (value instanceof OriginTrackedValue) {
                        value = ((OriginTrackedValue) value).getValue();  // 获取实际的配置值
                    }

                    // 如果该值是加密的，进行解密
                    if (value != null && value.toString().startsWith(ENCRYPTED_PREFIX)) {
                        try {
                            String decryptedValue = AESUtils.decrypt(value.toString().substring(ENCRYPTED_PREFIX.length()), "yourSecretKey");  // 密钥
                            decryptedProperties.put(key, decryptedValue);
                        } catch (Exception e) {
                            String failureReason = "Unknown error"; // 默认的失败原因

                            // 根据不同的异常类型设置失败原因
                            if (e instanceof InvalidKeyException) {
                                failureReason = "Invalid decryption key.";
                            } else if (e instanceof BadPaddingException) {
                                failureReason = "Bad padding in encrypted data.";
                            } else if (e instanceof IllegalBlockSizeException) {
                                failureReason = "Illegal block size in encrypted data.";
                            } else if (e instanceof NoSuchPaddingException) {
                                failureReason = "No such padding available for decryption.";
                            }

                            // 记录解密失败的属性及其原始值
                            System.err.println("Decryption failed for property: " + key);
                            System.err.println("Original value: " + value);
                            // 抛出自定义异常，指出是哪一个属性解密失败
                            //throw new DecryptionException(key, value.toString(), failureReason, e);
                        }
                    } else {
                        // 如果该值没有加密，直接保存
                        decryptedProperties.put(key, value);
                    }
                }
            }
        }

        // 创建一个新的 PropertySource，存储解密后的值
        MapPropertySource decryptedPropertySource = new MapPropertySource("decryptedProperties", decryptedProperties);

        // 将新的 PropertySource 添加到环境的属性源中
        environment.getPropertySources().addFirst(decryptedPropertySource);
    }
}
